package org.jeecg.modules.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @author cuirankang
 * @date 2020/3/11
 */
public class DateUtils {


    public static String fixFormat(String pattern) {
        String[] split = pattern.split("-");
        if(split.length ==3){
            if (split[1].length() <2){
                split[1] = "0"+split[1];
            }
            if (split[2].length() <2){
                split[2] = "0"+split[2];
            }
            return split[0]+"-"+split[1]+"-"+split[2];
        }
        return pattern;
    }
    /**
     * 获取格式化的时间
     * @author cuirankang
     * @date 2020/3/7
     */
    public static String getFormattedTime(String pattern) {

        SimpleDateFormat df = new SimpleDateFormat(pattern);
        return df.format(new Date());
    }

    public static int getDifferDays(Date srcDate,Date dstDate){
//       return Math.abs((int) (dstDate.getTime() - srcDate.getTime()/(1000* 3600 * 24)));
        return (int) ((dstDate.getTime() - srcDate.getTime())/(1000* 3600 * 24));
    }


    /**
     * 字符串转时间
     * @author cuirankang
     * @date 2020/3/7
     */
    public static Date str2Date(String day) throws ParseException {

        SimpleDateFormat df = new SimpleDateFormat("yyyy-mm-dd");

        return df.parse(day);
    }
    public  static LocalDateTime toLocalDateTime(String dateTimeStr, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return LocalDateTime.parse(dateTimeStr, formatter);
    }
    public  static LocalDate toLocalDate(String dateStr, String pattern) {

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(pattern);
        LocalDate formatterDate = LocalDate.parse(dateStr, dtf);

        return formatterDate;
    }
    public  static String format(LocalDate localDate, String pattern) {

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(pattern);

        return localDate.format(dtf);
    }

    public  static java.sql.Date local2Sql(LocalDate localDate) {
        return  java.sql.Date.valueOf(localDate);
    }
    public  static java.util.Date local2util(LocalDate localDate) {
        Instant instant = localDate.atTime(LocalTime.MIDNIGHT).atZone(ZoneId.systemDefault()).toInstant();
        return  java.util.Date.from(instant);
    }

    /**
     * 比较时间差几天（如果time1比time2晚，结果为正数，否则负数）
     * @author cuirankang
     * @date 2020/3/10
     */
    public static int compareDay(Date time1, Date time2) {

        Calendar c1 = Calendar.getInstance();
        c1.setTime(time1);
        Calendar c2 = Calendar.getInstance();
        c2.setTime(time2);

        int year1 = c1.get(Calendar.YEAR);
        int year2 = c2.get(Calendar.YEAR);
        int day = c1.get(Calendar.DAY_OF_YEAR) - c2.get(Calendar.DAY_OF_YEAR);
        int year = 0;
        if (year1 < year2) {
            for (int i = year1 ;i < year2 ;i++) {
                //闰年
                if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) {
                    year -= 366;
                } else {
                    year -= 365;
                }
            }
        } else if (year1 > year2) {
            for (int i = year2 ;i < year1 ;i++) {
                //闰年
                if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) {
                    year += 366;
                } else {
                    year += 365;
                }
            }
        }
        return year + day;
    }

    public static String getMonth(int month) {

        String monthStr =  String.valueOf(month);
        return monthStr.length() == 1 ? "0" + monthStr : monthStr;
    }

    public static String[] getLastMonth(int year, int month) {

        Calendar c = Calendar.getInstance();
        // month - 1用来对应Calendar的月份常量
        c.set(year, month - 1, 1);
        c.add(Calendar.MONTH, -1);
        SimpleDateFormat df = new SimpleDateFormat("MM");
        return new String[]{String.valueOf(c.get(Calendar.YEAR)), df.format(c.getTime())};
    }

    /**
     * 获取前6个月的年月信息
     * @author cuirankang
     * @date 2020/3/11
     */
    public static Map<String, Object> getLast6Month(int year, int month) {

        Map<String, Object> result = new HashMap<>(8);

        Calendar c = Calendar.getInstance();
        // month - 1用来对应Calendar的月份常量
        c.set(year, month - 1, 1);
        c.add(Calendar.MONTH, 1);
        for (int i = 1; i <= 6; i++) {
            c.add(Calendar.MONTH, -1);
            SimpleDateFormat df = new SimpleDateFormat("MM");
            result.put("year" + i, c.get(Calendar.YEAR));
            result.put("month" + i, df.format(c.getTime()));
        }
        return result;
    }

    /**
     * 获取季度对应的月份
     * @author cuirankang
     * @date 2020/3/20
     */
    public static String getMonthByQuarter(int quarter) {

        switch (quarter) {
            case 1:
                return "03";
            case 2:
                return "06";
            case 3:
                return "09";
            default:
                return "12";
        }
    }

    /**
     * 获取半年对应的月份
     * @author cuirankang
     * @date 2020/3/20
     */
    public static String getMonthByHalfYear(int halfYear) {

        switch (halfYear) {
            case 1:
                return "06";
            default:
                return "12";
        }
    }

    /**  
     * 获取季度的时间区间范围（左包含，右不包含）
     * @author cuirankang
     * @date 2020/3/11
     */
    public static Date[] getQuarterTimeScope(int year, Integer quarter) {

        Calendar c = Calendar.getInstance();
        c.set(year, Calendar.JANUARY, 1);
        Date time1 = c.getTime();
        c.add(Calendar.MONTH, 3);
        Date time2 = c.getTime();
        c.add(Calendar.MONTH, 3);
        Date time3 = c.getTime();
        c.add(Calendar.MONTH, 3);
        Date time4 = c.getTime();
        c.add(Calendar.MONTH, 3);
        Date time5 = c.getTime();

        switch (quarter) {
            case 1:
                return new Date[]{time1, time2};
            case 2:
                return new Date[]{time2, time3};
            case 3:
                return new Date[]{time3, time4};
            default:
                return new Date[]{time4, time5};
        }
    }

    /**
     * 获取季度的月份区间范围（左右包含）
     * @author cuirankang
     * @date 2020/3/12
     */
    public static String[] getQuarterMonthScope(int quarter) {

        switch (quarter) {
            case 1:
                return new String[]{"01", "03"};
            case 2:
                return new String[]{"04", "06"};
            case 3:
                return new String[]{"07", "09"};
            default:
                return new String[]{"10", "12"};
        }
    }

    /**
     * 获取年的时间区间范围（左包含，右不包含）
     * @author cuirankang
     * @date 2020/3/11
     */
    public static Date[] getYearTimeScope(int year) {

        Calendar c = Calendar.getInstance();
        c.set(year, Calendar.JANUARY, 1);
        Date time1 = c.getTime();
        c.add(Calendar.YEAR, 1);
        Date time2 = c.getTime();

        return new Date[]{time1, time2};
    }

    public static Map<String, String> getYearAndMonth() {
        Calendar date = Calendar.getInstance();
        int y = date.get(Calendar.YEAR);
        int m = date.get(Calendar.MONTH) + 1;
        int day = date.get(Calendar.DAY_OF_MONTH);
        Map<String, String> result = new HashMap<>();
        String month;
        //窗口期可能在下个月这个时候需要判断一下时间需不需要减少1月
        if (day < 11) {
            m -= 1;
            //如果等于0则月分为1月 这个时候应该查去年12月分的数据；
            if (m == 0) {
                y -= 1;
                m = 12;
            }
            result.put("inWindow", "true");
        } else {
            if (m == 12) {
                if (day > 19) {
                    result.put("inWindow", "true");
                }
            } else {
                if (day > 25) {
                    result.put("inWindow", "true");
                }
            }
        }
        if (m < 10) {
            month = "0" + m;
        } else {
            month = String.valueOf(m);
        }
        String year = String.valueOf(y);
        result.put("year", year);
        result.put("month", month);
        return result;
    }

    public static Map<String, String> getPrevYearAndMonth() {
        Map<String, String> result = new HashMap<>();
        Calendar date = Calendar.getInstance();
        int y = date.get(Calendar.YEAR);
        int m = date.get(Calendar.MONTH);
        int d = date.get(Calendar.DAY_OF_MONTH);
        String month;
        //窗口期可能在下个月这个时候需要判断一下时间需不需要减少1月
        //如果等于0则月分为1月 这个时候应该查去年12月分的数据；
        if (m == 0) {
            y -= 1;
            m = 12;
        }
        if (d<11)
            m -=1;
        if (m < 10) {
            month = "0" + m;
        } else {
            month = String.valueOf(m);
        }
        String year = String.valueOf(y);
        result.put("year", year);
        result.put("month", month);
        return result;
    }
    public static int getMonthQty(Date startDate,Date endDate){
        int monthQty = 0;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        // 获取开始年份和开始月份
        int startYear = calendar.get(Calendar.YEAR);
        int startMonth = calendar.get(Calendar.MONTH);
        // 获取结束年份和结束月份
        calendar.setTime(endDate);
        int endYear = calendar.get(Calendar.YEAR);
        int endMonth = calendar.get(Calendar.MONTH);
        //
        List<String> list = new ArrayList<String>();
        for (int i = startYear; i <= endYear; i++) {
            String date = "";
            if (startYear == endYear) {
                for (int j = startMonth; j <= endMonth; j++) {
                    if (j < 9) {
                        date = i + "-0" + (j + 1);
                    } else {
                        date = i + "-" + (j + 1);
                    }
                    list.add(date);
                }

            } else {
                if (i == startYear) {
                    for (int j = startMonth; j < 12; j++) {
                        if (j < 9) {
                            date = i + "-0" + (j + 1);
                        } else {
                            date = i + "-" + (j + 1);
                        }
                        list.add(date);
                    }
                } else if (i == endYear) {
                    for (int j = 0; j <= endMonth; j++) {
                        if (j < 9) {
                            date = i + "-0" + (j + 1);
                        } else {
                            date = i + "-" + (j + 1);
                        }
                        list.add(date);
                    }
                } else {
                    for (int j = 0; j < 12; j++) {
                        if (j < 9) {
                            date = i + "-0" + (j + 1);
                        } else {
                            date = i + "-" + (j + 1);
                        }
                        list.add(date);
                    }
                }

            }

        }

        if(list != null){
            monthQty = list.size();
        }
        return monthQty;
    }



    public static void main(String[] args) {
        LocalDate localDate1= DateUtils.toLocalDate("2023-04-26", "yyyy-MM-dd");
        LocalDate localDate2 = DateUtils.toLocalDate("2023-5-5", "yyyy-M-d");
        LocalDate localDate3 = DateUtils.toLocalDate("2023-5-25", "yyyy-M-d");
        showDate(localDate1);
        showDate(localDate2);
        showDate(localDate3);
        LocalDate formatDate = null;

  //              LocalDate常用用法
//                定义
        formatDate = LocalDate.of(2020, 2, 5); // 自定义
        LocalDate today = LocalDate.now(); // 获取当前日期
    //    getX() 获取年月日等
        System.out.println(formatDate.getMonth()); // FEBRUARY 获取所在月份（英文）
        System.out.println(formatDate.getMonthValue()); // 2 获取所在月份（英文）
        System.out.println(formatDate.getDayOfMonth()); // 5 获取所在天
      //  plusX()、minusX() 加减日期
        LocalDate nextDay = formatDate.plusDays(1);
        System.out.println(nextDay); // 2020-02-06 明天
        LocalDate nextWeek = formatDate.plusWeeks(1);
        System.out.println(nextWeek); // 2020-02-12 下周当天
        LocalDate lastMonth = formatDate.minusMonths(1);
        System.out.println(lastMonth); // 2020-01-05 上月当天
       // 扩展用法

         //       常用于报表中计算同比环比等日期
//        localDate 转 date
//
//
//   localDate 转 时间戳/


            long instant = localDate1.atStartOfDay(ZoneOffset.systemDefault()).toInstant().toEpochMilli();
            System.out.println(instant);
            LocalDateTime now = LocalDateTime.now();
            long instant1 = now.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
            System.out.println(instant1);
            //时间戳 转 localDate
        long time = new Date().getTime();
        LocalDateTime localDateTime = Instant.ofEpochMilli(time).atZone(ZoneOffset.systemDefault()).toLocalDateTime();
        System.out.println(localDateTime);
        LocalDate localDate11 = Instant.ofEpochMilli(time).atZone(ZoneOffset.systemDefault()).toLocalDate();
        System.out.println(localDate11);


// 同环比日期计算
        LocalDate firstWeekDay = formatDate.with(TemporalAdjusters.previous(DayOfWeek.MONDAY));
        System.out.println(firstWeekDay); // 2020-02-03 本周第一天
        LocalDate firstMonthDay = formatDate.with(TemporalAdjusters.firstDayOfMonth());
        System.out.println(firstMonthDay); // 2020-02-01 本月第一天
        LocalDate firstYearDay = formatDate.with(TemporalAdjusters.firstDayOfYear());
        System.out.println(firstYearDay); // 2020-01-01 本年第一天
        System.out.println(today.with(TemporalAdjusters.lastDayOfMonth())); // 当月的最后一天
// 1表示当月第一个  星期天  正数表示，第几个星期天，可能会超过当月
        System.out.println(today.with(TemporalAdjusters.dayOfWeekInMonth(1,DayOfWeek.SUNDAY)));
// 注 -1表示当月最后一个  星期天  负数表示: 如-4 =-1 -3  比表示当前月最后一天，往前3星期
        System.out.println(today.with(TemporalAdjusters.dayOfWeekInMonth(-1,DayOfWeek.SUNDAY)));

// 1表示当月第一个  星期天  正数表示，第几个星期天，可能会超过当月
        System.out.println(today.with(TemporalAdjusters.dayOfWeekInMonth(1,DayOfWeek.SUNDAY)));
// 判断两个日期前后
        boolean param = formatDate.isBefore(today);
        System.out.println(param); // true 判断a是否早于b
// 计算两个日期的间隔天数
        LocalDate start = LocalDate.parse("2019-12-01");
        LocalDate end = LocalDate.parse("2020-02-05");
        long days = start.until(end, ChronoUnit.DAYS);
        System.out.println("days: " + days); // days: 66
//        LocalDateTime与String互转
// LocalDateTime 转字符串
// 第一种方法
        String date1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now());
// 第二种方法
        String date2 = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        System.out.println(date1);
        System.out.println(date2);


// 字符串转 LocalDateTime
// 第一种方法
        LocalDateTime dateTime2 = LocalDateTime.parse("2021-01-18 02:35:59", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

// 第二种方法
        TemporalAccessor temporalAccessor = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").parse("2021-01-18 02:31:29");
        LocalDateTime dateTime1 = LocalDateTime.from(temporalAccessor);

        System.out.println(dateTime1);
        System.out.println(dateTime2);
//        计算时间差值
        LocalDate startDate = LocalDate.of(2020, 2, 20);
        LocalDate endDate = LocalDate.of(2021, 1, 15);

        System.out.printf("相差%d年",ChronoUnit.YEARS.between(startDate, endDate));
        System.out.printf("相差%d月",ChronoUnit.MONTHS.between(startDate, endDate));
        System.out.printf("相差%d周", ChronoUnit.WEEKS.between(startDate, endDate));
        System.out.printf("相差%d天",ChronoUnit.DAYS.between(startDate, endDate));
        System.out.printf("相差%d小时",ChronoUnit.HOURS.between(startDate, endDate));
        System.out.printf("相差%d分钟",ChronoUnit.MINUTES.between(startDate, endDate));
        System.out.printf("相差%d秒",ChronoUnit.SECONDS.between(startDate, endDate));
        System.out.printf("相差%d微秒",ChronoUnit.MILLIS.between(startDate, endDate));
        System.out.printf("相差%d毫微秒",ChronoUnit.NANOS.between(startDate, endDate));

        List<String> list = IntStream.rangeClosed(0, 6).boxed()
                .map(daysToSubtract -> LocalDate.now().minusDays(daysToSubtract).toString())
                .collect(Collectors.toList());
        list.forEach(System.out::println);
    }

    private static void showDate(LocalDate localDate) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        System.out.println( dtf.format(localDate));
        System.out.println(localDate.getYear());
        System.out.println(localDate.getMonth());

        System.out.println(localDate.getDayOfMonth());
        System.out.println("----");
    }

    public static Date local2util(LocalDateTime dateTime) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt =dateTime.atZone(zoneId);
        return Date.from(zdt.toInstant());
    }

    public static LocalDate util2local(Date date) {
//        Date date = new Date();
        Instant instant = date.toInstant();

        ZoneId zoneId = ZoneId.systemDefault();

        return instant.atZone(zoneId).toLocalDate();
    }

    public static LocalDateTime util2localDateTime(Date date) {
//        Date date = new Date();
        Instant instant = date.toInstant();

        ZoneId zoneId = ZoneId.systemDefault();

        return instant.atZone(zoneId).toLocalDateTime();
    }
}
